import { useSafeState, useMemoizedFn, useMount } from 'ahooks';
import type { RequestType, Obj, RequestResult } from './types';

export function useSplitPage<R = any>(request: RequestType<R>, pageSize = 10) {
  const [page, setPage] = useSafeState(1);
  const [empty, setEmpty] = useSafeState(false);
  const [error, setError] = useSafeState<any>(null);
  const [noMore, setNoMore] = useSafeState(false);
  const [datas, setDatas] = useSafeState<R[]>([]);
  const [loading, setLoading] = useSafeState(true);
  const [refreshing, setRefreshing] = useSafeState(false);

  const _loading = refreshing || loading;

  const onRequest = useMemoizedFn(async (current = 1, params?: Obj) => {
    const isRefresh = current === 1;
    const result = await request({
      params,
      pageSize,
      page: current
    });
    let list = result.list;
    list = isRefresh ? list : [...datas, ...list];
    const noMore = list.length >= result.total;
    return { ...result, list, noMore };
  });

  // 网络请求
  const handleRequest = useMemoizedFn(async (params?: Obj) => {
    let error = null;
    try {
      const {
        list,
        noMore,
      } = await onRequest(page, params);
      setNoMore(noMore);
      if (list.length) {
        setDatas(list);
        setPage(page + 1);
      } else {
        setEmpty(true);
      }
      return { list, page };
    } catch (err) {
      error = err;
      return Promise.reject(err);
    } finally {
      setError(error);
      setLoading(false);
      setRefreshing(false);
    }
  });

  const runRequest = useMemoizedFn((params?: Obj) => {
    return new Promise<RequestResult<R>>((resolve, reject) => (
      requestIdleCallback(async () => {
        try {
          const result = await handleRequest(params);
          resolve(result);
        } catch (err) {
          reject(err);
        }
      })
    ));
  });

  // 下一页
  const toNextPage = useMemoizedFn(() => {
    const noData = noMore || empty;
    if (noData || _loading) return;
    setLoading(true);
    return runRequest();
  });

  // 刷新
  const refresh = useMemoizedFn(async (params?: Obj) => {
    if (_loading) return;
    setPage(1);
    setNoMore(false);
    setRefreshing(true);
    return runRequest(params);
  });

  const getDatas = useMemoizedFn(() => {
    return { list: datas, page };
  });

  useMount(handleRequest);

  return {
    page,
    empty,
    error,
    datas,
    noMore,
    refresh,
    loading,
    getDatas,
    refreshing,
    toNextPage
  }
}